#include <qlistview.h>
#include <qcombobox.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qlayout.h>

#include "KeyBindWidget.h"
#include "KeyBindManager.h"
#include "keycodeutil.h"

KeyBindWidget::KeyBindWidget(KeyBindManager *man, QWidget *parent): QWidget(parent),
		manager(man)
{
	bindList = new QListView(this);
	bindList->addColumn(tr("Qt"));
	bindList->addColumn(tr("Host"));
	bindList->addColumn(tr("Shift"));
	bindList->setSelectionMode(QListView::Single);
	bindList->setAllColumnsShowFocus(true);
	bindList->setRootIsDecorated(false);
	bindList->setShowSortIndicator(true);
	bindList->setSorting(0);
	
	qtKeys = new QComboBox(false, this);
	for (int i = 0; QtKeyPairs[i].code != Qt::Key_unknown; ++i)
		qtKeys->insertItem(QtKeyPairs[i].name);
	
	hostKeys = new QComboBox(false, this);
	for (int i = 0; HostKeyPairs[i].code != 0x00; ++i)
		hostKeys->insertItem(HostKeyPairs[i].name);
	
	shift = new QCheckBox(tr("Shift"), this);
	
	QHBoxLayout *kl = new QHBoxLayout();	// key list layout
	kl->addWidget(qtKeys);
	kl->addWidget(hostKeys);
	kl->addWidget(shift);
	
	QPushButton *add, *change, *remove;
	add = new QPushButton(tr("add"), this);
	connect(add, SIGNAL(clicked()), this, SLOT(addBind()));
	change = new QPushButton(tr("change"), this);
	connect(change, SIGNAL(clicked()), this, SLOT(changeBind()));
	remove = new QPushButton(tr("remove"), this);
	connect(remove, SIGNAL(clicked()), this, SLOT(removeBind()));
	
	QPushButton *reset, *clear;
	reset = new QPushButton(tr("reset default"), this);
	connect(reset, SIGNAL(clicked()), this, SLOT(resetDefaultBind()));
	clear = new QPushButton(tr("clear all"), this);
	connect(clear, SIGNAL(clicked()), this, SLOT(clearAllBind()));
	
	QHBoxLayout *bl = new QHBoxLayout();	// button layout
	bl->addWidget(add);
	bl->addWidget(change);
	bl->addWidget(remove);
	bl->addWidget(clear);
	bl->addWidget(reset);
	
	QVBoxLayout *l = new QVBoxLayout(this);
	l->addLayout(kl);
	l->addLayout(bl);
	l->addWidget(bindList);
	
	reloadKeyBindManager();
}

void KeyBindWidget::addBind()
{
	for (QListViewItemIterator it(bindList); it.current(); ++it)
		if (it.current()->text(0) == qtKeys->currentText())
			return;
	
	new QListViewItem(bindList, qtKeys->currentText(), hostKeys->currentText(), (shift->isChecked() ? "*" : ""));
}

void KeyBindWidget::changeBind()
{
	QListViewItem *item = bindList->selectedItem();
	if (item == NULL)	return;
	
	// check duplication
	for (QListViewItemIterator it(bindList); it.current(); ++it)
		if (it.current()->text(0) == qtKeys->currentText() && it.current() != item)
			return;
	
	// should use enum for column index
	item->setText(0, qtKeys->currentText());
	item->setText(1, hostKeys->currentText());
	item->setText(2, (shift->isChecked() ? "*" : ""));
}

void KeyBindWidget::removeBind()
{
	QListViewItem *item = bindList->selectedItem();
	if (item == NULL)	return;
	
	bindList->takeItem(item);
	delete item;
}

void KeyBindWidget::resetDefaultBind()
{
	manager->setDefaultBind();
	reloadKeyBindManager();
}

void KeyBindWidget::clearAllBind()
{
	manager->clear();
	reloadKeyBindManager();
}

void KeyBindWidget::updateKeyBindManager()
{
	manager->clear();
	for (QListViewItemIterator it(bindList); it.current(); ++it)
		manager->appendBind(
				QtKeyCodeByName(it.current()->text(0)),
				KeyBindManager::Key(HostKeyCodeByName(it.current()->text(1)), (it.current()->text(2).isEmpty() ? false : true))
			);
}

void KeyBindWidget::reloadKeyBindManager()
{
	bindList->clear();
	// load saved bind
	const KeyBindManager::BindMap &binds = manager->bindMap();
	for (KeyBindManager::BindMap::ConstIterator it = binds.begin(); it != binds.end(); ++it)
		new QListViewItem(bindList, QtKeyNameByCode(it.key()), HostKeyNameByCode(it.data().code), (it.data().shift ? "*" : ""));
}
